/*******************************************************************************
 * Copyright 2010 DemandSpot
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.demandspot.client.table;



public enum FilterOperation {
	EQUALS {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return value.compareTo(cellValue) == 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}

		public String htmlString() {
			return "=";
		}
	},	
	GREATER_THEN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return cellValue.compareTo(value) > 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}

		public String htmlString() {
			return ">";
		}
	},	
	LESS_THEN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return cellValue.compareTo(value) < 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}

		public String htmlString() {
			return "<";
		}
	},	
	EQUALS_GREATER_THEN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return cellValue.compareTo(value) >= 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}

		public String htmlString() {
			return ">=";
		}
	},
	EQUALS_LESS_THEN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return cellValue.compareTo(value) <= 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}

		public String htmlString() {
			return "<=";
		}
	},
	NOT_EQUALS {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			C value = cellRenderer.getCompareValue(values.trim());
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			return cellValue.compareTo(value) != 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			cellRenderer.getCompareValue(values.trim());
		}
		
		public String htmlString() {
			return "<>";
		}
	},
	IN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			for (String part : parts) {
				C value = cellRenderer.getCompareValue(part.trim());
				if (cellValue.compareTo(value) == 0) {
					return true;
				}
			}
			return false;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			for (String string : parts) {
				cellRenderer.getCompareValue(string.trim());
			}
		}
		
		public String htmlString() {
			return "In";
		}
	},
	NOT_IN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			for (String part : parts) {
				C value = cellRenderer.getCompareValue(part.trim());
				if (cellValue.compareTo(value) == 0) {
					return false;
				}
			}
			return true;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			for (String string : parts) {
				cellRenderer.getCompareValue(string.trim());
			}
		}
		
		public String htmlString() {
			return "Not In";
		}
	},
	BETWEEN {
		public <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			C cellValue = cellRenderer.getCompareValue(cellRenderer.getDisplayedString(model));
			C leftPart = cellRenderer.getCompareValue(parts[0].trim());
			C rightPart = cellRenderer.getCompareValue(parts[1].trim());
			
			
			return cellValue.compareTo(leftPart) >=0 && cellValue.compareTo(rightPart) <= 0;
		}

		public <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values) {
			String[] parts = values.split(CellRenderer.FILTER_SEPARATOR);
			if (parts.length != 2) {
				throw new IllegalArgumentException();
			}
			for (String string : parts) {
				cellRenderer.getCompareValue(string.trim());
			}
		}
		
		public String htmlString() {
			return "Between";
		}
	};
	
	public abstract <T, C extends Comparable<C>> boolean doOperation(T model, CellRenderer<T, C> cellRenderer, String values);
	public abstract <T, C extends Comparable<C>>  void validate(CellRenderer<T, C> cellRenderer, String values);
	public abstract String htmlString();
	
	public static FilterOperation[] numberDefaultOperations() {
		return FilterOperation.values();
	}
	
	public static FilterOperation[] stringDefaultOperations() {
		return new FilterOperation[]{EQUALS, NOT_EQUALS, IN, NOT_IN};
	}
	
	public static FilterOperation[] dateDefaultOperations() {
		return FilterOperation.values();
	}
}
